/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.dtgenerator.core.rtgen.entitygen.createdtmassmethodgen;

import com.inspur.edp.bef.core.determination.builtinimpls.predicate.ExecutePredicateFactory;
import com.inspur.edp.cef.designtime.api.operation.ChildDtmTriggerInfo;
import com.inspur.edp.cef.designtime.api.operation.CommonDetermination;
import com.inspur.edp.cef.designtime.api.operation.ExecutingDataStatus;
import com.inspur.edp.cef.generator.coreGenerator.base.entitygen.EntityImplGenContext;
import com.inspur.edp.cef.generator.overall.GenUtils;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.das.commonmodel.entity.GspCommonObject;
import java.util.Map.Entry;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.MethodInvocation;

public class CreateDtmAssMethodUtil {
  public static Expression buildPredicate(AST ast, CommonDetermination op, EntityImplGenContext entityGenCtx){
    MethodInvocation agInvocation=ast.newMethodInvocation();
    agInvocation.setExpression(ast.newName(ExecutePredicateFactory.class.getSimpleName()));
    agInvocation.setName(ast.newSimpleName("getAggregatePredicate"));

    addByDataStatus(ast, op, entityGenCtx, agInvocation);
    addByChildTriggerInfo(ast, op, entityGenCtx, agInvocation);

    return agInvocation;
  }

  private static void addByChildTriggerInfo(AST ast, CommonDetermination op, EntityImplGenContext entityGenCtx,
      MethodInvocation agInvocation) {
    if(op.getChildTriggerInfo() == null) {
      return;
    }

    for(Entry<String, ChildDtmTriggerInfo> entry: op.getChildTriggerInfo().entrySet()) {
      String childObjId = entry.getKey();
      IGspCommonObject childObj = ((GspCommonObject) entityGenCtx.getDataType()).getChildObjectById(childObjId);
      ChildDtmTriggerInfo childDtmTriggerInfo = entry.getValue();
      if (childDtmTriggerInfo.getGetExecutingDataStatus() != null) {
        for (ExecutingDataStatus ds : childDtmTriggerInfo.getGetExecutingDataStatus()) {
          switch(ds) {
            case added:
              MethodInvocation childAddInvocation = GenUtils
                  .getMethodInvocation(ast,
                      ast.newName(ExecutePredicateFactory.class.getSimpleName()),
                      "getChildAddPredicate");
              childAddInvocation.arguments().add(GenUtils.buildStringLiteral(ast, childObj.getCode()));
              agInvocation.arguments().add(childAddInvocation);
              break;
            case Deleted:
              MethodInvocation childDeleteInvocation = GenUtils
                  .getMethodInvocation(ast,
                      ast.newName(ExecutePredicateFactory.class.getSimpleName()),
                      "getChildDeletePredicate");
              childDeleteInvocation.arguments().add(GenUtils.buildStringLiteral(ast, childObj.getCode()));
              agInvocation.arguments().add(childDeleteInvocation);
//              predicates.add(ExecutePredicateFactory.getChildDeletePredicate(childObj.getCode()));
              break;
            case Modify:
              MethodInvocation childModifyInvocation = GenUtils
                  .getMethodInvocation(ast,
                      ast.newName(ExecutePredicateFactory.class.getSimpleName()),
                      "getChildModifyPredicate");
              childModifyInvocation.arguments().add(GenUtils.buildStringLiteral(ast, childObj.getCode()));
              if(childDtmTriggerInfo.getRequestChildElements() != null && !childDtmTriggerInfo.getRequestChildElements().isEmpty()) {
                childModifyInvocation.arguments().add(GenUtils
                    .buildRequestElementsList(ast, childObj, childDtmTriggerInfo.getRequestChildElements()));
              } else {
                childModifyInvocation.arguments().add(ast.newNullLiteral());
              }
              agInvocation.arguments().add(childModifyInvocation);
              break;
            case None:
              break;
            default:
              throw new RuntimeException(ds.toString());
          }
        }
      }
    }
  }

  private static void addByDataStatus(AST ast, CommonDetermination op, EntityImplGenContext entityGenCtx,
      MethodInvocation agInvocation) {
    if (op.getGetExecutingDataStatus() == null) {
      return;
    }
    for (ExecutingDataStatus dataStatus : op.getGetExecutingDataStatus()) {
      switch (dataStatus) {
        case Modify:
          MethodInvocation modifyInvocation = GenUtils
              .getMethodInvocation(ast, ast.newName(ExecutePredicateFactory.class.getSimpleName()),
                  "getModifyPredicate");
          if(op.getRequestElements() != null && !op.getRequestElements().isEmpty()) {
            modifyInvocation.arguments().add(GenUtils
                .buildRequestElementsList(ast, entityGenCtx.getDataType(), op.getRequestElements()));
          } else {
            modifyInvocation.arguments().add(ast.newNullLiteral());
          }
          agInvocation.arguments().add(modifyInvocation);
          break;
        case Deleted:
          agInvocation.arguments().add(GenUtils
              .getMethodInvocation(ast, ast.newName(ExecutePredicateFactory.class.getSimpleName()),
                  "getDeletePredicate"));
          break;
        case added:
          agInvocation.arguments().add(GenUtils
              .getMethodInvocation(ast, ast.newName(ExecutePredicateFactory.class.getSimpleName()),
                  "getAddPredicate"));
          break;
        case None:
          break;
        default:
          throw new RuntimeException(dataStatus.toString());
      }
    }
  }

  public static boolean anyChildRequestElement(CommonDetermination op) {
    return op.getRequestChildElements() != null && !op.getRequestChildElements().isEmpty()
        && op.getRequestChildElements().values().stream().anyMatch(item -> item != null && !item.isEmpty());
  }
}
